package com.jc.order.service.impl;

import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jc.order.common.OrderNumberGenerator;
import com.jc.order.domain.EciCustomerQuotaApply;
import com.jc.order.dto.EciCustomerQuotaApplyDTO;
import com.jc.order.dto.Query;
import com.jc.order.mapper.EciCustomerQuotaApplyMapper;
import com.jc.order.service.EciCustomerQuotaApplyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EciCustomerQuotaApplyServiceImpl implements EciCustomerQuotaApplyService {

    private static final int MAX_BATCH_SIZE = 500; // 批量操作最大尺寸

    @Resource
    private EciCustomerQuotaApplyMapper eciCustomerQuotaApplyMapper;

    @Override
    public EciCustomerQuotaApplyDTO queryById(Long id, Long tenantId) {
        Example example = new Example(EciCustomerQuotaApply.class);
        example.createCriteria()
                .andEqualTo("tenantId", tenantId)
                .andEqualTo("id", id);
        EciCustomerQuotaApply entity = eciCustomerQuotaApplyMapper.selectOneByExample(example);
        return entity != null ? toDTO(entity) : null;
    }

    @Override
    public PageInfo<EciCustomerQuotaApplyDTO> paginQuery(Query query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<EciCustomerQuotaApply> list = eciCustomerQuotaApplyMapper.queryAllByLimit(query.getM());
        return new PageInfo<>(toDTOs(list));
    }

    @Transactional
    @Override
    public EciCustomerQuotaApplyDTO createQuotaApply(EciCustomerQuotaApplyDTO dto) {
        if (dto == null) return null;

        dto.setCorpSerialNo(OrderNumberGenerator.generate("ECI"));
        EciCustomerQuotaApply entity = toEntity(dto);
        eciCustomerQuotaApplyMapper.insert(entity);
        dto.setId(entity.getId());
        return dto;
    }

    @Transactional
    @Override
    public Boolean updateQuotaApply(EciCustomerQuotaApplyDTO dto) {
        Example example = new Example(EciCustomerQuotaApply.class);
        example.createCriteria()
                .andEqualTo("tenantId", dto.getTenantId())
                .andEqualTo("corpSerialNo", dto.getCorpSerialNo());

        return eciCustomerQuotaApplyMapper.updateByExampleSelective(
                toEntity(dto), example) > 0;
    }

    @Override
    public EciCustomerQuotaApplyDTO getBySerialNo(String corpSerialNo, Long tenantId) {
        Example example = new Example(EciCustomerQuotaApply.class);
        example.createCriteria()
                .andEqualTo("tenantId", tenantId)
                .andEqualTo("corpSerialNo", corpSerialNo);

        EciCustomerQuotaApply entity = eciCustomerQuotaApplyMapper.selectOneByExample(example);
        return entity != null ? toDTO(entity) : null;
    }

    @Override
    public List<EciCustomerQuotaApplyDTO> getBySerialNoList(List<String> corpSerialNoList, Long tenantId) {
        if (CollectionUtils.isEmpty(corpSerialNoList))
            return Collections.emptyList();

        // 限制批量查询大小
        if (corpSerialNoList.size() > MAX_BATCH_SIZE) {
            log.warn("批量查询数量过大: {} > {}", corpSerialNoList.size(), MAX_BATCH_SIZE);
            corpSerialNoList = corpSerialNoList.subList(0, MAX_BATCH_SIZE);
        }

        Example example = new Example(EciCustomerQuotaApply.class);
        example.createCriteria()
                .andEqualTo("tenantId", tenantId)
                .andIn("corpSerialNo", corpSerialNoList);

        return toDTOs(eciCustomerQuotaApplyMapper.selectByExample(example));
    }

    @Override
    public EciCustomerQuotaApplyDTO getByCompName(String compName, Long tenantId) {
        Example example = new Example(EciCustomerQuotaApply.class);
        Example.Criteria criteria = example.createCriteria()
                .andEqualTo("riskCompName", compName);

        if (tenantId != null) {
            criteria.andEqualTo("tenantId", tenantId);
        }

        EciCustomerQuotaApply entity = eciCustomerQuotaApplyMapper.selectOneByExample(example);
        return entity != null ? toDTO(entity) : null;
    }

    @Override
    public EciCustomerQuotaApplyDTO getByRiskMark(String riskMark, Long tenantId) {
        Example example = new Example(EciCustomerQuotaApply.class);
        example.createCriteria()
                .andEqualTo("tenantId", tenantId)
                .andEqualTo("riskMark", riskMark);

        EciCustomerQuotaApply entity = eciCustomerQuotaApplyMapper.selectOneByExample(example);
        return entity != null ? toDTO(entity) : null;
    }

    @Override
    public List<EciCustomerQuotaApplyDTO> getByDTO(EciCustomerQuotaApplyDTO applyDTO) {
        Example example = new Example(EciCustomerQuotaApply.class);
        example.createCriteria().andEqualTo("tenantId", applyDTO.getTenantId());

        Example.Criteria orCriteria = example.and();
        orCriteria.orEqualTo("riskMark", applyDTO.getRiskMark())
                .orEqualTo("riskCompName", applyDTO.getRiskCompName());

        if (StrUtil.isNotEmpty(applyDTO.getCorpSerialNo())) {
            orCriteria.orEqualTo("corpSerialNo", applyDTO.getCorpSerialNo());
        }

        return toDTOs(eciCustomerQuotaApplyMapper.selectByExample(example));
    }

    @Override
    public Map<String, EciCustomerQuotaApplyDTO> getByCompNames(List<String> compNames) {
        if (CollectionUtils.isEmpty(compNames))
            return Collections.emptyMap();

        // 限制批量查询大小
        if (compNames.size() > MAX_BATCH_SIZE) {
            log.warn("公司名称批量查询数量过大: {} > {}", compNames.size(), MAX_BATCH_SIZE);
            compNames = compNames.subList(0, MAX_BATCH_SIZE);
        }

        Example example = new Example(EciCustomerQuotaApply.class);
        example.createCriteria().andIn("riskCompName", compNames);

        return eciCustomerQuotaApplyMapper.selectByExample(example).stream()
                .map(this::toDTO)
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                        EciCustomerQuotaApplyDTO::getRiskCompName,
                        Function.identity()
                ));
    }

    @Transactional
    @Override
    public void batchUpdate(List<EciCustomerQuotaApplyDTO> list) {
        if (CollectionUtils.isEmpty(list)) return;

//        // 分批次处理避免超大事务
//        int batchSize = Math.min(list.size(), 100);
//        for (int i = 0; i < list.size(); i += batchSize) {
//            int endIndex = Math.min(i + batchSize, list.size());
//            List<CustomerQuotaApplyDTO> batch = list.subList(i, endIndex);
//
//            // 批量更新数据库
//            batch.forEach(this::updateQuotaApply);
//        }

        for (int i = 0; i < list.size(); i++) {
            EciCustomerQuotaApplyDTO applyDTO = list.get(i);
            this.updateQuotaApply(applyDTO);
        }
    }

    // ============== 私有工具方法 ==============

    private EciCustomerQuotaApplyDTO toDTO(EciCustomerQuotaApply entity) {
        if (entity == null) return null;
        EciCustomerQuotaApplyDTO dto = new EciCustomerQuotaApplyDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

    private EciCustomerQuotaApply toEntity(EciCustomerQuotaApplyDTO dto) {
        EciCustomerQuotaApply entity = new EciCustomerQuotaApply();
        BeanUtils.copyProperties(dto, entity);
        return entity;
    }

    private List<EciCustomerQuotaApplyDTO> toDTOs(List<EciCustomerQuotaApply> entities) {
        if (CollectionUtils.isEmpty(entities))
            return Collections.emptyList();

        return entities.stream()
                .map(this::toDTO)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
}